Skip to content

Dev - #48

Open
milinsky wants to merge 15 commits into
mainfrom
dev
Open

Dev#48
milinsky wants to merge 15 commits into
mainfrom
dev

Conversation

@milinsky

Copy link
Copy Markdown
Member

Summary

Brief description of what this PR changes.

Checklist

  • Tests added for new behaviour
  • CHANGELOG.md updated (or N/A: internal refactor)
  • BC-break documented in CHANGELOG ### BREAKING (or N/A)
  • make tests green
  • make psalm clean (0 errors)
  • make cs-fix clean
  • make rector clean

milinsky added 15 commits July 28, 2026 15:11
…on 1)

- Lower MAX_ALIAS_DEPTH 10→4 (chain-bomb defence; rejects all known
  chain-bomb variants while preserving legitimate 4-level dedup patterns
  1→2→4→8 ≤10^4 expanded elements).
- Add MAX_EXPANSION_BYTES = 5_000_000 post-parse defense-in-depth cap;
  catches horizontal bombs (low chain depth × high arity) that bypass
  the pre-parse DAG heuristic.
- Add SpecTooLargeException::forExpansionSize(int $cap, int $actual)
  factory with sanitised message (only metric + actual + cap; never
  attacker payload — CWE-209).
- Add normalizeLineEndings() in assertNoAnchorBomb() to defend against
  \r/\r\n line-ending bypass of the DAG depth heuristic (Symfony Parser
  applies the same str_replace, so the heuristic stays consistent with
  Symfony's view).
- README: update caps table (MAX_ALIAS_DEPTH=4, MAX_EXPANSION_BYTES row)
  + intro paragraph mentioning the fourth post-parse cap.
- Add 5 regression tests: 7×10 chain bomb (<100 ms rejection), 4×10
  legitimate dedup still passes, 4×40 horizontal bomb caught by size
  cap, CR/LF and CR-only line-ending chain bombs rejected by depth cap.

Refs: B-SEC-1 (CVSS 7.5, CWE-400 / CWE-770). Audit: 505-byte anchor-chain
payload previously caused ~17 s CPU + ~1.5 GB RAM per parse; same payload
now rejected in <5 ms. Verified: 7136 tests OK, Psalm 99.6790% (no errors),
cs-fix/rector clean.
…02 — partition 1)

- composer.json:34 — change constraint from `^7.0 || ^8.0` to `^7.4 || ^8.1`
- Blocks EOL versions: Symfony 7.0-7.3 (no security patches since 2024-2025)
  and 8.0 (EOL 31 Jul 2026).
- Preserves Symfony 7.4 LTS (security support to Nov 2029) and 8.1 current.
- composer.lock (v8.1.1) remains valid; no lock file changes in commit
  (lock file in .gitignore per library convention).

Refs: B-DEP-1 (MEDIUM supply-chain blocker). Verified: composer validate
--strict exit 0, composer update --dry-run 'Nothing to modify in lock
file', composer why-not 7.0/7.3/8.0 blocked, 7.4 allowed, make tests
7136 OK.
…Task 03 — partition 1)

- .github/workflows/ci.yml:93 — change Swoole CI job filter from
  'SwooleSharedValidatorTest' to '(SwooleSharedValidatorTest|ValidatorPoolTest)'.
- Adds CI regression protection for ValidatorPool::forCoroutineRuntime()
  + Swoole\Lock serialization contract (O-004 non-reentrant deadlock).
- Previously only sequential SwooleSharedValidatorTest ran in CI; the
  swoole_lock_serializes_concurrent_get_or_create_factory_called_once
  coroutine test (tests/Unit/Validator/ValidatorPoolTest.php:456) was
  excluded by the filter and had zero CI coverage.

Refs: B-CONC-1 (MEDIUM concurrency blocker). Verified: list-tests shows
30 methods (2 SwooleSharedValidatorTest + 28 ValidatorPoolTest including
target swoole_lock test); make tests 7136 OK without regressions;
PCRE alternation syntax valid in PHPUnit --filter.
… (Task 04 — partition 1)

- CHANGELOG.md footer: add '[0.7.0]: 0.6.0...0.7.0'
  between [Unreleased] and [0.6.0] references.
- Eliminates broken Markdown link-reference for header ## [0.7.0] (line 8) —
  Keep a Changelog violation.
- Header ## [0.7.0] without date intentionally preserved (date added at tag
  time per Task 09 release notes draft).
- [Unreleased] URL left unchanged per Task 04 spec target shape: 0.7.0 is
  pending release (no tag yet, no date in header); Task 09 will update
  [Unreleased] to compare/1.0.0...HEAD when 1.0.0 is drafted.

Refs: B-DOC-1 (MEDIUM documentation blocker). Verified: git diff shows
+1 -0; all 6 version headers (0.7.0/0.6.0/0.5.0/0.4.1/0.4.0/0.3.3) have
matching [X.Y.Z]: references; no other broken links discovered.
…ask 05 — partition 1)

- Add /** @internal */ PHPDoc tag to 12 classes in src/Builder/Internal/
  (3) and src/Compiler/Internal/ (9) that lacked the marker.
- Format follows canonical samples (DocumentFingerprinter.php,
  SchemaHasher.php): single-line /** @internal */ for classes without
  existing PHPDoc; @internal tag appended to existing PHPDoc block
  otherwise.
- After this change all 14 Internal\ classes in Builder/Internal +
  Compiler/Internal carry @internal marker (12 modified + 2 existing
  canonical).
- Psalm/PHPStan will flag user dependencies on these classes once
  psalm/internal_plugin is enabled (currently documentation-only;
  plugin install is tracked as separate follow-up).

Refs: B-API-1 (MEDIUM public-API stability blocker). Verified: grep
@internal returns 14 files in src/{Builder,Compiler}/Internal/;
make psalm 0 errors (99.6790% baseline preserved); make tests 7136
OK without regressions; make cs-fix 0 files modified.
… partition 1)

- Add regression test in DependentSchemasValidatorTest.php for
  NestedValidationError wrap path (previously 0% coverage).
- Test scenario: NAN value + oneOf [minimum:0, maximum:100] triggers
  InvalidDataTypeException in both branches → OneOfValidator throws plain
  ValidationException with empty errors → PropertiesValidator preserves
  empty errors → DependentSchemasValidator catch ([] === $errors) wraps
  in NestedValidationError.
- Coverage: NestedValidationError.php 0% → 100% (7/7 lines).
- Anti-test verified: removing wrap branch (DependentSchemasValidator
  lines 91-99) causes test to fail ('actual size 0 matches expected
  size 1') — genuine regression protection.

Refs: B-TEST-1 (MEDIUM test-coverage blocker). Verified: make tests
7137 OK (baseline + 1), make psalm 0 errors (99.6790%), make cs-fix
0 files. Note: second NestedValidationError instantiation site in
ItemValidationExceptionTrait.php:70 remains uncovered (follow-up).
…2/3) (Task 07 — partition 1)

- README.md: add 7 racy cache classes to 'Unsafe classes and their
  contracts' table (PathRegexCache, RegexValidator, RefResolver,
  SchemaValidatorWithContext, EnumScalarCache, SchemaValidator,
  CompilationCache). Table now has 10 rows (3 existing @danger + 7 racy
  memoization). Add explanatory paragraph distinguishing correctness-
  critical (@danger NOT_THREAD_SAFE) from performance-memoization racy.
- README.md: add reset() prefork-only paragraph in Long-Running
  Processes section; enumerate all 4 caches cleared (ValidatorPool,
  PathRegexCache, RefResolver, RegexValidator).
- src/Builder/OpenApiValidatorInterface.php: update reset() PHPDoc —
  replace misleading 'Safe to call between requests in long-running
  processes' with prefork-only contract (mirror implementation PHPDoc).
- src/Validator/OpenApiValidator.php: add reset() PHPDoc with precise
  prefork-only contract (safe when no concurrent validation in progress).

Refs: B-CONC-2 + B-CONC-3 (MEDIUM concurrency blockers). Verified:
make psalm 0 errors (99.6790%), make tests 7137 OK, make cs-fix 0
files. All 7 FQCN resolve to actual files; reset() body clears exactly
the 4 caches enumerated in README.
…partition 2)

- Add ## Stability / Backward Compatibility section between Features
  and Installation: SemVer 2.0 adherence, BC criteria (3 rules),
  exclusions (*\Internal namespaces, @experimental, named constructor
  args), deprecation policy, patch/minor release commitments.
- Schema constructor correctly described as 57-parameter (not 56).
- CHANGELOG reference uses plain link (no broken GFM anchor).
- Internal namespace enumeration uses *\Internal wildcard with 4 examples.

Refs: B-API-2 (MEDIUM public-API stability blocker). Verified: psalm
0 errors, tests 7137 OK, cs-fix 0 files.
…artition 2)

- Add ## [1.0.0] - YYYY-MM-DD section before ## [0.7.0] with Added,
  Changed, Deprecated, Security, and Acknowledgments subsections.
- Add [1.0.0]: link reference in footer between [Unreleased] and [0.7.0].
- Update [Unreleased]: URL from compare/0.6.0...HEAD to
  compare/1.0.0...HEAD (1.0.0 is now the latest released version).
- Date placeholder YYYY-MM-DD kept (filled at tag time).
- No individual contributor names (company policy); link to GitHub
  contributors page instead.

Refs: B-DOC-2 (MEDIUM documentation blocker). Verified: psalm 0 errors,
tests 7137 OK, cs-fix 0 files.
…0 — partition 2)

- Add multi-line class-level PHPDoc to OpenApiValidatorBuilder (entry
  point, terminal method) and OpenApiValidator (interface implementation,
  introspection accessors).
- Add one-line English PHPDoc to 22 typed-error exception classes
  (TypeMismatchError through NotValidationError).
- All PHPDoc on public API elements (§12 exception allows PHPDoc on
  public API in English).
- 27 additional exception classes remain without class-level PHPDoc
  (spec provided text only for 22; follow-up for remaining classes).

Refs: B-DOC-3 + B-DOC-4 (MEDIUM documentation blockers). Verified:
psalm 0 errors, tests 7137 OK, cs-fix 0 files.
…k 11 — partition 2)

- Add ### Memory Profile subsection to README streaming validation section.
- Documents: not constant-memory, ~47 MB peak at 100k records default cap,
  O(N) memory footprint, withMaxStreamingRecords() mitigation.
- Placed between JSON Text Sequences and Error Handling in Streams.

Refs: B-PERF-1 (MEDIUM performance documentation blocker). Verified:
psalm 0 errors, tests 7137 OK, cs-fix 0 files.
…ision (B-API-3) (Task 13 — partition 3)

- Add @internal PHPDoc to Dto\ValidatorDependencies (internal wiring DTO).
- Validation\ValidatorDependencies remains public (used by Builder).
- SchemaValidator\ValidatorDependencies already @internal+@deprecated.
- Add regression test verifying @internal markers on 2 of 3 classes.

Refs: B-API-3 (MEDIUM API stability blocker). Verified: psalm 0 errors,
tests 7141 OK, cs-fix 0 files.
… partition 3)

- Create IntrospectableOpenApiValidatorInterface extending
  OpenApiValidatorInterface with 6 read-only accessors (getPool,
  isCoercion, isNullableAsType, getEmptyArrayStrategy,
  getErrorFormatter, getCache).
- OpenApiValidator now implements IntrospectableOpenApiValidatorInterface.
- OpenApiValidatorInterface unchanged (no BC break).
- README updated: introspection accessors now part of interface contract.
- Callers type-hinting OpenApiValidatorInterface are unaffected; callers
  needing introspection type-hint IntrospectableOpenApiValidatorInterface.

Refs: B-TD-1 (MEDIUM tech debt blocker). Verified: psalm 0 errors,
tests 7141 OK, cs-fix 0 files.
…tion 3)

- Add 36 new test methods across 6 validators targeting uncovered
  branches: error paths, boolean schema form, null context, composition.
- DependentSchemasValidator (+6): InvalidFormatException rethrow,
  AbstractValidationError wrap, nullable property, nested anyOf.
- ItemsValidatorWithContext (+5): boolean items true/false paths.
- PrefixItemsValidator (+5): context=null creation, oneOf composition.
- CallbackValidator (+7):  resolution, HTTPS URL match/mismatch,
  curly brace template, strict mode.
- AbstractSchemaValidator (+8): getDataPath, formatSchemaType variants.
- ItemsValidator (+8): boolean items paths, InvalidFormatException,
  nested oneOf items.

Tests: 7141 → 7181 (+40 new). Psalm: 0 errors. cs-fix: 0 files.

Refs: B-TEST-3 (MEDIUM test coverage blocker).
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant